home *** CD-ROM | disk | FTP | other *** search
/ 130 MIDI Tool Box / 130 MIDI Tool Box.iso / mccutil / mpupro.txt next >
Text File  |  1986-08-31  |  73KB  |  2,094 lines

  1. ####################################################################
  2. The text following is six separate program files, three each for two
  3. separate programs.  They are separated by a line of "###'s" and must
  4. be each culled out of this file before assembly or compilation.  The
  5. first three files are "MPRIM.ASM", "MPU.H", and "TESTMPU.C".  These
  6. comprise the beginning of an interrupt driven program using the
  7. Roland MPU-401 in its "intelligent" mode.  This might be assumed to
  8. be the best mode for writing sequencer and recorder programs,
  9. especially if memory resources are limited.  There is a drawback in
  10. this mode, in that any software written for it becomes chained to
  11. usage with the MPU.  If you have an eye to transporting your work to
  12. such as the Arari/ST, this is not so good.  Also, while the MPU is
  13. impressive, it was designed to be memory efficient when used as the
  14. foundation for a sequencer/recorder.  If you are looking to set up
  15. musical phrases as, say LISP s-expressions, it might not be so great. 
  16. For these two reasons, and for others I haven't thought of, you might
  17. want to put the MPU to sleep, and just use it as a dumb MIDI port.
  18. The second three program files do just that.  They are "MIDI.ASM", 
  19. "MIDI.H", and "TESTMIDI.C"  All were written for the Microsoft
  20. Assembler version 3 or higher, and the Microsoft C compiler, version
  21. 4 (the new one).  Both resulting programs do work on my Kaypro 286i
  22. (an AT-clone).  They may or may not work on your machine.  I have
  23. left the copyright notice intact because I wish to emphasize that
  24. these programs are suitable only for pointing other MPU programmers
  25. in the right direction.  There are dead ends and (likely) errors. 
  26. Used with caution as a guide to your own programs, they might be
  27. usefull.  Used without thought or understanding, and I guarantee they
  28. will be more trouble than they are worth.  With that cheery thought,
  29. I wish you good luck.
  30.  
  31.                John Dunn
  32.                January, 1986  
  33.  
  34. ###############################################################
  35.         PAGE    60,127
  36.         TITLE   MPU primitives
  37.         NAME    MPRIM
  38.         .SALL
  39. ;==============================================================
  40. ; COPYRIGHT (C) 1986 John Dunn
  41. ;--------------------------------------------------------------
  42. ; date:        01/02/86
  43. ; update:      01/02/86
  44. ; last hacker: John Dunn
  45. ;==============================================================
  46. PRIM_TEXT       SEGMENT  BYTE PUBLIC 'CODE'
  47. PRIM_TEXT       ENDS
  48. CONST   SEGMENT  WORD PUBLIC 'CONST'
  49. CONST   ENDS
  50. _BSS    SEGMENT  WORD PUBLIC 'BSS'
  51. _BSS    ENDS
  52. _DATA   SEGMENT  WORD PUBLIC 'DATA'
  53. _DATA   ENDS
  54. DGROUP  GROUP   CONST,  _BSS,   _DATA
  55. ;==============================================================
  56. _DATA   SEGMENT  WORD PUBLIC 'DATA'
  57. ;--------------------------------------------------------------
  58.         PUBLIC  _indexp,_indext,_channel,_rtmsg,_pending
  59.         PUBLIC  _recording,_playing,_loading,_enderr
  60. ;--------------------------------------------------------------
  61. _channel dw     0               ; current midi channel
  62. _rtmsg  dw      0               ; real time message flag
  63. _pending dw     0               ; number of sys excl pending
  64. _recording dw   0               ; nz when recording track data
  65. _playing dw     0               ; nz when playing track data
  66. _loading dw     0               ; nz when loading para data       
  67. _enderr dw      0               ; nz if put index at limit
  68. _indext dw      0               ; index track buffer
  69. _indexp dw      0               ; index param buffer
  70. startt  dw      0               ; start track buffer
  71. startp  dw      0               ; start param buffer
  72. endtrk  dw      0               ; end track buffer
  73. endpar  dw      0               ; end param buffer
  74. limitt  dw      tbufx-_tbuf     ; track buffer limit
  75. limitp  dw      pbufx-_pbuf     ; param buffer limit
  76.  
  77. icount  dw      0               ; midi msg count index
  78. rcount  dw      0               ; midi msg run count
  79. pcount  dw      0               ; play track count
  80.  
  81. clkblp  dw      0               ; clock blip count
  82.  
  83. intval dw       0               ; inte data value
  84. special dw      0               ; nz = special routine
  85. sptable dw      dotimev,procsm,sysexc,songsel,songp1,songp2
  86.  
  87. ;--------------------------------------------------------------
  88. _DATA   ENDS
  89. ;==============================================================
  90. PBUF_DATA   SEGMENT PARA MEMORY 'BUFFER'
  91. ;--------------------------------------------------------------
  92.         PUBLIC  _pbuf
  93. ;--------------------------------------------------------------
  94. _pbuf   db      17000 dup(?)     ; parameter buffer
  95. pbufx   db      0
  96. ;--------------------------------------------------------------
  97. PBUF_DATA   ENDS
  98. ;==============================================================
  99. TBUF_DATA   SEGMENT PARA MEMORY 'BUFFER'
  100. ;--------------------------------------------------------------
  101.         PUBLIC  _tbuf
  102. ;--------------------------------------------------------------
  103. _tbuf  db      16384 dup(?)     ; parameter buffer
  104. tbufx  db      0
  105. ;--------------------------------------------------------------
  106. TBUF_DATA   ENDS
  107. ;==============================================================
  108. PRIM_TEXT      SEGMENT
  109.         ASSUME  CS: PRIM_TEXT, DS: DGROUP, SS: DGROUP, ES: DGROUP
  110. ;==============================================================
  111. bpo     equ 6           ; base pointer offset
  112.                                 ; 6 = large model; 4 = small
  113. p1      equ bpo                 ; single word arg 1, use [bp+@1]
  114. p2      equ bpo+2       ; single word arg 2, use [bp+@2]
  115. ;--------------------------------------------------------------
  116. mdata  equ 0330H               ; mpu data port address
  117. mstat  equ 0331H               ; mpu status port address
  118. mcmd   equ 0331H               ; mpu command port address
  119. mdsr   equ 80H                 ; mpu data set ready, active low
  120. mdrr   equ 40H                 ; mpu data read ready, active low
  121. ;--------------------------------------------------------------
  122. ; initialize mpu, int vectors, etc.
  123. ; must be called once only on startup
  124. ;
  125.         public  _initm
  126. _initm  proc    far
  127.         push    es              ; save current es
  128.         mov     ah,35h          ; get current int 2
  129.         mov     al,0AH
  130.         int     21H
  131.         mov     word ptr cs:orgint+3,es        ; save it
  132.         mov     word ptr cs:orgint+1,bx
  133.         pop     es              ; restore es
  134.  
  135.         push    ds              ; save current ds
  136.         mov     ah,25H          ; set int vect
  137.         mov     al,0AH          ; int 2 for MPU
  138.         mov     dx,seg mpuint
  139.         mov     ds,dx
  140.         mov     dx,offset mpuint
  141.         int     21H             ; set new int vect
  142.         pop     ds              ; restore ds
  143.  
  144.         mov     dx,mdata        ; clear data port
  145.         in      al,dx
  146.  
  147.         in      al,21H          ; enable irq2
  148.         jmp     short $+2       ; delay for AT 
  149.         and     al,0FBH
  150.         out     21H,al
  151.         sti                     ; enable ints
  152.         ret
  153. _initm  endp                     ; end of init mpu
  154.  
  155. ;--------------------------------------------------------------
  156. ; shutdown mpu, restore int vectors, etc.
  157. ; must be called once only on exit
  158. ;
  159.         public  _exitm
  160. _exitm  proc    far
  161.         in      al,21H          ; disable irq2
  162.         jmp     short $+2       ; delay for AT 
  163.         or      al,4
  164.         out     21H,al
  165.  
  166.         push    ds
  167.         mov     ah,25h          ; restore previous irq2
  168.         mov     al,0AH
  169.         mov     dx,word ptr cs:orgint+3
  170.         mov     ds,dx
  171.         mov     dx,word ptr cs:orgint+1
  172.         int     21h
  173.         pop     ds
  174.         ret
  175. _exitm  endp
  176.  
  177. ;--------------------------------------------------------------
  178. ; this routine is only called by int 2
  179. ; if it was not generated by the mpu, it vectors
  180. ; to the original int address, otherwise it saves
  181. ; registers, then calls the c routine _mpuint,
  182. ; after which it restores registers, clears nmi
  183. ; and returns from int. 
  184. ;
  185. mpuint  proc    far
  186.         push    ax              ; save ax
  187.         push    dx
  188.         mov     dx,mstat        ; read mpu status
  189. mpui0:  jmp     short $+2
  190.         in      al,dx
  191.         and     al,mdsr         ; generated by mpu?
  192.         jz      mpui1           ; yes, branch
  193. ;        jmp     mpui0
  194.         pop     dx              ; no, restore cpu
  195.         pop     ax
  196.         iret                    ; return from interrupt
  197. orgint: jmp     far ptr intval  ; dummy vector, filled by _initm
  198.         dw      0
  199.  
  200. mpui1:
  201.         push    bx              ; save cpu state
  202.         push    cx
  203.         push    di
  204.         push    si
  205.         push    bp
  206.         push    ds
  207.         push    es
  208.  
  209.         mov     ax,seg dgroup   ; set up c seg regs
  210.         mov     ds,ax
  211.         mov     es,ax
  212.  
  213.         mov     dx,mdata        ; get mpu int data
  214.         in      al,dx
  215.  
  216.         call    dompu           ; do the mpu routine
  217.  
  218.         pop     es              ; restore seg regs
  219.         pop     ds
  220.         pop     bp              ; restore cpu state
  221.         pop     si
  222.         pop     di
  223.         pop     cx
  224.         pop     bx
  225.         pop     dx
  226.         mov     al,20H          ; send eoi to 8259
  227.         out     20H,al
  228.         pop     ax
  229.         iret                    ; return from interrupt
  230. mpuint  endp
  231.  
  232.  
  233. ;--------------------------------------------------------------
  234. ; dompu
  235. ; process mpu inte
  236. ; local call
  237. ;
  238. dompu   proc    near
  239.         mov     byte ptr intval,al ; save as global variable
  240.         mov     bx,special
  241.         or      bx,bx           ; special flag set?
  242.         jz      dompu1          ; no, branch
  243.         dec     bx              ; yes, jump to special routine
  244.         add     bx,bx
  245.         mov     dx,sptable[bx]
  246.         jmp     dx
  247. dompu1: cmp     al,0F0H         ; < F0H
  248.         jnb     dompu2          ; no, branch
  249.         jmp     timev           ; yes, do time value
  250. dompu2: cmp     al,0F8H         ; < F8H
  251.         jnb     dompu3          ; no, branch
  252.         jmp     trackd          ; yes, do track data request
  253. dompu3: jnz     dompu4          ; branch if not = F8H
  254.         jmp     timeo           ; else do timing overflow
  255. dompu4: cmp     al,0F9H         ; = F9?
  256.         jnz     dompu5          ; no, branch
  257.         jmp     condr           ; yes, do conductor request
  258. dompu5: cmp     al,0FDH         ; = FD?
  259.         jnz     dompu6          ; no, branch
  260.         jmp     clockh          ; yes, do clock to host
  261. dompu6: cmp     al,0FCH         ; = FD?
  262.         jnz     dompu7          ; no, branch
  263.         jmp     allend          ; yes, do all end
  264. dompu7: cmp     al,0FFH         ; = FF?
  265.         jnz     dompu8          ; no, branch
  266.         jmp     midism          ; yes, do midi system message
  267. dompu8: ret
  268. dompu   endp
  269.  
  270. ;--------------------------------------------------------------
  271. ; mpuput(data)
  272. ; send data to mpu-401
  273. ; C call
  274. ;
  275.         public  _mpuput
  276. _mpuput proc    far
  277.         push    bp
  278.         mov     bp,sp
  279.  
  280.         mov     dx,mstat        ; mpu status port
  281. mpup1:  in      al,dx           ; get the status
  282.         and     al,mdrr         ; test for Data Recieve Ready
  283.         jnz     mpup1           ; loop til ready
  284.         mov     dx,mdata        ; mpu data port
  285.         mov     ax,[bp+p1]      ; get the data
  286.         out     dx,al           ; send to mpu
  287.  
  288.         mov     sp,bp           ; restore C sp
  289.         pop     bp
  290.         ret                     ; exit
  291. _mpuput endp
  292.  
  293. ;--------------------------------------------------------------
  294. ; mpuput
  295. ; send data in AL to mpu-401
  296. ; local call, AX is preserved
  297. ;
  298. mpuput  proc    near
  299.     push    ax
  300.         mov     dx,mstat        ; mpu status port
  301. mpupa1: in      al,dx           ; get the status
  302.         and     al,mdrr         ; test for Data Recieve Ready
  303.         jnz     mpupa1          ; loop til ready
  304.         mov     dx,mdata        ; mpu data port
  305.         pop     ax              ; get the data
  306.         out     dx,al           ; send to mpu
  307.         ret                     ; exit
  308. mpuput  endp
  309.  
  310. ;--------------------------------------------------------------
  311. ; data=mpuget()
  312. ; get data from mpu-401
  313. ; C call
  314. ;
  315.         public  _mpuget
  316. _mpuget proc    far
  317.  
  318.         mov     dx,mstat        ; mpu status port
  319. mpug1:  in      al,dx           ; get the status
  320.         and     al,mdsr         ; test for Data Set Ready
  321.         jnz     mpug1           ; loop til ready
  322.         mov     dx,mdata        ; mpu data port
  323.         in      al,dx           ; get the data byte
  324.         mov     ah,0            ; zero out ms byte
  325.         ret                     ; exit with ax = data
  326. _mpuget endp
  327.  
  328. ;--------------------------------------------------------------
  329. ; mpuget
  330. ; get data from mpu-401 to AX
  331. ; local call
  332. ;
  333. mpuget  proc    near
  334.         mov     dx,mstat        ; mpu status port
  335. mpuga1: in      al,dx           ; get the status
  336.         and     al,mdsr         ; test for Data Set Ready
  337.         jnz     mpuga1          ; loop til ready
  338.         mov     dx,mdata        ; mpu data port
  339.         in      al,dx           ; get the data byte
  340.         mov     ah,0            ; zero out ms byte
  341.         ret                     ; exit with ax = data
  342. mpuget  endp
  343.  
  344. ;--------------------------------------------------------------
  345. ; mpucmd(cmd)
  346. ; send a command to mpu-401
  347. ;
  348.         public  _mpucmd
  349. _mpucmd proc    far
  350.         push    bp
  351.         mov     bp,sp
  352.  
  353.         mov     dx,mstat        ; mpu status port
  354. mpuc1:  in      al,dx           ; get the status
  355.         and     al,mdrr         ; test for Data Recieve Ready
  356.         jnz     mpuc1           ; loop til ready
  357.         cli                     ; disable intes
  358.         mov     ax,[bp+p1]      ; get the command
  359.         out     dx,al           ; send to mpu
  360. mpuc2:  in      al,dx           ; get the status
  361.         and     al,mdsr         ; test for Data Set Ready
  362.         jnz     mpuc2           ; loop til ready
  363.         mov     dx,mdata        ; mpu data port
  364.         in      al,dx           ; read it
  365.         cmp     al,0FEH         ; acknowledge?
  366.         jz      mpuc3           ; yes, branch
  367.  
  368.         push    di              ; save C registers
  369.         push    si
  370.         call    dompu           ; do mpu routine
  371.         pop     si
  372.         pop     di
  373.         mov     dx,mstat        ; mpu status port
  374.         jmp     short mpuc2     ; check again for ack
  375.  
  376. mpuc3:  sti                     ; enable ints
  377.         mov     sp,bp           ; restore C sp
  378.         pop     bp
  379.         ret                     ; exit
  380. _mpucmd endp
  381.  
  382. ;--------------------------------------------------------------
  383. ; data = gett()
  384. ; get byte from track buffer
  385. ; C call
  386. ;
  387.         public  _gett
  388. _gett   proc    far
  389.         mov     bx,_indext      ; get index
  390.         mov     dx,seg _tbuf
  391.         push    ds
  392.         mov     ds,dx           ; fetch the data
  393.         mov     al,ds:[bx]
  394.         xor     ah,ah           ; ax = data
  395.         pop     ds
  396.         inc     bx              ; inc index
  397.         cmp     bx,endtrk       ; reached end?
  398.         jnz     gett1           ; no, exit
  399.         mov     bx,startt       ; yes, set index = start
  400. gett1:  mov     _indext,bx      ; save index
  401.         ret                     ; exit with ax = data
  402. _gett   endp
  403.  
  404. ;--------------------------------------------------------------
  405. ; gett
  406. ; get byte to AX from track buffer
  407. ; local call
  408. ;
  409. gett    proc    near
  410.         mov     bx,_indext      ; get index
  411.         mov     dx,seg _tbuf
  412.         push    ds
  413.         mov     ds,dx           ; fetch the data
  414.         mov     al,ds:[bx]
  415.         xor     ah,ah           ; ax = data
  416.         pop     ds
  417.         inc     bx              ; inc index
  418.         cmp     bx,endtrk       ; reached end?
  419.         jnz     getta1          ; no, exit
  420.         mov     bx,startt       ; yes, set index = start
  421. getta1: mov     _indext,bx      ; save index
  422.         ret                     ; exit with ax = data
  423. gett   endp
  424.  
  425. ;--------------------------------------------------------------
  426. ; putt(track_data)
  427. ; put byte to track buffer
  428. ; C call
  429. ;
  430.         public  _putt
  431. _putt   proc    far
  432.         push    bp
  433.         mov     bp,sp
  434.         mov     bx,_indext      ; get index
  435.         mov     dx,seg _tbuf
  436.         mov     al,[bp+p1]      ; get the data
  437.         push    ds
  438.         mov     ds,dx           ; store the data
  439.         mov     ds:[bx],al
  440.         pop     ds
  441.         inc     bx              ; inc index
  442.         cmp     bx,limitt       ; reached limit?
  443.         mov     ax,1            ; flag error
  444.         jz      putt0           ; yes, branch with err
  445.         mov     ax,0            ; no, flag no-error
  446.         mov     _indext,bx      ; store index
  447.         mov     endtrk,bx       ; end = index
  448. putt0:  mov     _enderr,ax      ; save in _enderr
  449.         mov     sp,bp           ; restore C sp
  450.         pop     bp
  451.         ret                     ; exit
  452. _putt   endp
  453.  
  454. ;--------------------------------------------------------------
  455. ; putt
  456. ; put byte in AL to track buffer
  457. ; local call
  458. ;
  459. putt    proc    near
  460.         mov     bx,_indext      ; get index
  461.         mov     dx,seg _tbuf
  462.         push    ds
  463.         mov     ds,dx           ; store the data
  464.         mov     ds:[bx],al
  465.         pop     ds
  466.         inc     bx              ; inc index
  467.         cmp     bx,limitt       ; reached limit?
  468.         mov     ax,1            ; flag error
  469.         jz      putta0          ; yes, branch with err
  470.         mov     ax,0            ; no, flag no-error
  471.         mov     _indext,bx      ; store index
  472.         mov     endtrk,bx       ; end = index
  473. putta0: mov     _enderr,ax      ; save in _enderr
  474.         ret                     ; exit
  475. putt    endp
  476.  
  477. ;--------------------------------------------------------------
  478. ; data = getp()
  479. ; get byte from parameter buffer
  480. ; C call
  481. ;
  482.         public  _getp
  483. _getp   proc    far
  484.         mov     bx,_indexp      ; get index
  485.         mov     dx,seg _pbuf
  486.         push    ds
  487.         mov     ds,dx           ; fetch the data
  488.         mov     al,ds:[bx]
  489.         xor     ah,ah           ; ax = data
  490.         pop     ds
  491.         inc     bx              ; inc index
  492.         cmp     bx,endpar       ; reached end?
  493.         jnz     getp1           ; no, exit
  494.         mov     bx,startp       ; yes, set index = start
  495. getp1:  mov     _indexp,bx      ; save index
  496.         ret                     ; exit with ax = data
  497. _getp   endp
  498.  
  499. ;--------------------------------------------------------------
  500. ; getp
  501. ; get byte to AX from param buffer
  502. ; local call
  503. ;
  504. getp    proc    near
  505.         mov     bx,_indexp      ; get index
  506.         mov     dx,seg _pbuf
  507.         push    ds
  508.         mov     ds,dx           ; fetch the data
  509.         mov     al,ds:[bx]
  510.         xor     ah,ah           ; ax = data
  511.         pop     ds
  512.         inc     bx              ; inc index
  513.         cmp     bx,endpar       ; reached end?
  514.         jnz     getpa1          ; no, exit
  515.         mov     bx,startp       ; yes, set index = start
  516. getpa1: mov     _indexp,bx      ; save index
  517.         ret                     ; exit with ax = data
  518. getp   endp
  519.  
  520. ;--------------------------------------------------------------
  521. ; putp(param_data)
  522. ; put byte to param buffer
  523. ; C call
  524. ;
  525.         public  _putp
  526. _putp   proc    far
  527.         push    bp
  528.         mov     bp,sp
  529.         mov     bx,_indexp      ; get index
  530.         mov     dx,seg _pbuf
  531.         mov     al,[bp+p1]      ; get the data
  532.         push    ds
  533.         mov     ds,dx           ; store the data
  534.         mov     ds:[bx],al
  535.         pop     ds
  536.         inc     bx              ; inc index
  537.         cmp     bx,limitp       ; reached limit?
  538.         mov     ax,1            ; flag error
  539.         jz      putp0           ; yes, branch with err
  540.         mov     ax,0            ; no, flag no-error
  541.         mov     _indexp,bx      ; store index
  542.         mov     endpar,bx       ; end = index
  543. putp0:  mov     _enderr,ax      ; save in _enderr
  544.         mov     sp,bp           ; restore C sp
  545.         pop     bp
  546.         ret                     ; exit
  547. _putp   endp
  548.  
  549. ;--------------------------------------------------------------
  550. ; putp
  551. ; put byte in AL to param buffer
  552. ; local call
  553. ;
  554. putp    proc    near
  555.         mov     bx,_indexp      ; get index
  556.         mov     dx,seg _pbuf
  557.         push    ds
  558.         mov     ds,dx           ; store the data
  559.         mov     ds:[bx],al
  560.         pop     ds
  561.         inc     bx              ; inc index
  562.         cmp     bx,limitp       ; reached limit?
  563.         mov     ax,1            ; flag error
  564.         jz      putpa0          ; yes, branch with err
  565.         mov     ax,0            ; no, flag no-error
  566.         mov     _indexp,bx      ; store index
  567.         mov     endpar,bx       ; end = index
  568. putpa0: mov     _enderr,ax      ; save in _enderr
  569.         ret                     ; exit
  570. putp    endp
  571.  
  572. ;--------------------------------------------------------------
  573. ; timeo
  574. ; process timing overflow on inte
  575. ; local call with intval in AL
  576. ;
  577. timeo   proc    near
  578.         call    putt
  579.         ret
  580. timeo   endp
  581.  
  582. ;--------------------------------------------------------------
  583. ; condr
  584. ; process conductor request on inte
  585. ; local dummy routine, sends timing overflow byte
  586. ;
  587. condr   proc    near
  588.         mov     al,0F8H
  589.         call    putt
  590.         ret
  591. condr   endp
  592.  
  593. ;--------------------------------------------------------------
  594. ; clockh
  595. ; process clock to host on inte
  596. ; local call 
  597. ;
  598. clockh  proc    near
  599.         mov     ax,clkblp       ; get blip flag
  600.         inc     ax              ; count up
  601.         and     ax,1
  602.         mov     clkblp,ax       ; put back
  603.         inc     ax              ; 1,2 = happy face
  604.         mov     cx,ds
  605.         mov     dx,0B800H       ; point to gx screen
  606.         mov     ds,dx
  607.         mov     byte ptr ds:9EH,al ; display blip
  608.         mov     ds,cx
  609.         ret
  610. clockh  endp
  611.  
  612. ;--------------------------------------------------------------
  613. ; allend
  614. ; process all end on inte
  615. ; local call, clears playing flag
  616. ;
  617. allend  proc    near
  618.         mov     ax,0
  619.         mov     _playing,ax
  620.         ret
  621. allend  endp
  622.  
  623. ;--------------------------------------------------------------
  624. ; timev
  625. ; process time value on inte
  626. ; local call with intval in AL
  627. ;
  628. timev   proc    near
  629.         call    putt
  630.         mov     ax,1            ; set special = 1
  631.         mov     special,ax      ; dotimev on next inte
  632.         ret
  633. timev   endp
  634.  
  635. ;--------------------------------------------------------------
  636. ; dotimev (special = 1 )
  637. ; next inte processing of time value
  638. ; local call with intval in AL
  639. ;
  640. dotimev proc    near
  641.         cmp     al,0F8H         ; mpu mark, no operation
  642.         jz      dotime1
  643.         cmp     al,0F9H         ; mpu mark, measure end
  644.         jz      dotime2
  645.         cmp     al,0FCH         ; mpu mark, data end
  646.         jnz     dotime3
  647.         mov     ax,0
  648.         mov     _recording,ax   ; clr recording flag
  649. dotime2:call    putt            ; put in record buffer
  650. dotime1:mov     ax,0
  651.         mov     special,ax      ; done, clear special
  652.         ret                     ; exit
  653. dotime3:mov     ah,al           ; get a copy
  654.         and     ah,0F0H         ; zip channel data
  655.         cmp     ah,0C0H         ; midi msg, program change
  656.         jz      dotime4
  657.         cmp     ah,0DH          ; midi msg, channel pressure
  658.         jnz     dotime5
  659. dotime4:mov     dx,1            ; set to recieve 1 more byte
  660.         jmp     short dotime6
  661. dotime5:cmp     ah,80H          ; midi msg, note off
  662.         jz      dotime7
  663.         cmp     ah,90H          ; midi msg, note on
  664.         jz      dotime7
  665.         cmp     ah,0A0H         ; midi msg, after touch
  666.         jz      dotime7
  667.         cmp     ah,0B0H         ; midi msg, control change
  668.         jz      dotime7
  669.         cmp     ah,0E0H         ; midi msg, pitch wheel
  670.         jnz     dotime8
  671. dotime7:mov     dx,2            ; set to recieve 2 more bytes
  672. dotime6:mov     rcount,dx
  673.         mov     icount,dx
  674.         call    putt            ; put in record buffer
  675.         ret                     ; exit
  676. dotime8:and     ah,80H          ; < 7FH ?
  677.         jz      dotime9         ; yes, branch
  678.         mov     ax,0            ; no, is error
  679.         mov     special,ax      ; clear special
  680.         call    far ptr _beep   ; signal error
  681.         ret                     ; exit
  682. dotime9:mov     ah,byte ptr icount ; get current count
  683.         cmp     ah,0            ; new one?
  684.         jnz     dotim10         ; no, branch
  685.         mov     ah,byte ptr rcount ; yes, icount <-- rcount
  686. dotim10:push    ax              ; save it
  687.         call    putt            ; save the data byte in AL
  688.         pop     ax              ; ah = icount
  689.         dec     ah              ; dec icount
  690.         mov     byte ptr icount,ah ; save it
  691.         jnz     dotime11        ; branch if icount not 0
  692.         mov     ax,0            ; else clear special
  693.         mov     special,ax
  694. dotime11:ret                    ; exit
  695. dotimev endp
  696.  
  697. ;--------------------------------------------------------------
  698. ; trackd
  699. ; process track play request on inte
  700. ; local call with intval in AL
  701. ;
  702. trackd  proc    near
  703.         call    gett            ; get next track buffer byte
  704.         nop                     ; fix midi channel
  705.         call    mpuput          ; send it to mpu data port
  706.         cmp     al,0F8H         ; midi timing overflow
  707.         jnz     trackd1
  708.         ret                     ; just exit if it was timing overfow
  709. trackd1:call    gett            ; get next track buffer byte
  710.         nop                     ; fix midi channel
  711.         call    mpuput          ; send it to mpu data port
  712.         and     al,0F0H         ; strip midi channel info
  713.         cmp     al,0F0H         ; mpu mark
  714.         jnz     trackd2
  715.         ret
  716. trackd2:test    al,80H          ; <= 7FH ?
  717.         jnz     trackd3         ; no, branch
  718.         cmp     pcount,1        ; pcount = 1 ?
  719.         jnz     trackd4         ; no, branch
  720.         ret                     ; yes, exit
  721. trackd3:cmp     al,0C0H         ; one byte needed?
  722.         jz      trackd5
  723.         cmp     al,0D0H
  724.         jnz     trackd6
  725. trackd5:mov     pcount,1        ; yes, set running pcount to 1
  726.         jmp     short trackd4   ; ... and get one more byte 
  727. trackd6:mov     pcount,2        ; else set running pcount to 2
  728.         call    gett            ; get next track buffer byte
  729.         nop                     ; fix midi channel
  730.         call    mpuput          ; send it to mpu data port
  731. trackd4:call    gett            ; get next track buffer byte
  732.         nop                     ; fix midi channel
  733.         call    mpuput          ; send it to mpu data port
  734.         ret
  735. trackd  endp
  736.  
  737. ;--------------------------------------------------------------
  738. ; midism
  739. ; process midi system message on inte
  740. ; local call
  741. ;
  742. midism  proc    near
  743.         mov     ax,2            ; flag special = 2
  744.         mov     special,ax      ; procsm on next inte
  745.         ret
  746. midism  endp
  747.  
  748. ;--------------------------------------------------------------
  749. ; procsm ( special = 2)
  750. ; continue to process midi system message in inte
  751. ; local call with intval in AL
  752. ;
  753. procsm  proc    near
  754.         cmp     al,0F0H         ; midi exclusive
  755.         jnz     procsm1
  756.         call    putp            ; save in para buffer
  757.         mov     ax,1            ; set loading flag
  758.         mov     _loading,ax
  759.         mov     ax,3            ; set special = 3
  760.         mov     special,ax      ; continue on next inte
  761.         ret
  762. procsm1:cmp     al,0F3H         ; song select
  763.         jnz     procsm2
  764.         mov     ax,4            ; set special = 4
  765.         mov     special,ax      ; continue on next inte
  766.         ret
  767. procsm2:cmp     al,0F2H         ; song position
  768.         jnz     procsm3
  769.         mov     ax,5            ; set special = 5
  770.         mov     special,ax      ; continue on next inte
  771.         ret
  772. procsm3:cmp     al,0F6H         ; tune request
  773.         jnz     procsm4
  774.         nop                     ; insert routine here
  775.         jmp     short procsm0   ; clr special & exit     
  776. procsm4:mov     byte ptr _rtmsg,al ; flag real time message
  777. procsm0:mov     ax,0            ; clear special
  778.         mov     special,ax
  779.         ret                     ; exit        
  780. procsm  endp
  781.  
  782. ;--------------------------------------------------------------
  783. ; sysexc (special = 3 )
  784. ; inte processing of system exclusive values
  785. ; local call with intval in AL
  786. ;
  787. sysexc  proc    near
  788.         push    ax              ; save inte value
  789.         call    putp            ; save in parameter buffer
  790.         pop     ax
  791.         cmp     al,0F7H         ; was it EOX
  792.         jnz     sysexc0         ; no, just exit
  793.         mov     ax,0            ; yes,
  794.         mov     _loading,ax     ; clear loading flag
  795.         mov     special,ax      ; clear special
  796.         inc     word ptr _pending ; inc pending flag
  797. sysexc0:ret                     ; exit
  798. sysexc  endp
  799.  
  800. ;--------------------------------------------------------------
  801. ; songsel (special = 4)
  802. ; inte processing of song select
  803. ; local call with intval in AL
  804. ;
  805. songsel proc    near
  806.         nop                     ; dummy routine
  807.         mov     ax,0            ; clear special
  808.         mov     special,ax
  809.         ret
  810. songsel endp
  811.  
  812. ;--------------------------------------------------------------
  813. ; songp1 (special = 5)
  814. ; inte processing of song position 1st byte
  815. ; local call with intval in AL
  816. ;
  817. songp1  proc    near
  818.         nop                     ; dummy routine
  819.         mov     ax,6            ; special = 6
  820.         mov     special,ax      ; songp2 on next int
  821.         ret
  822. songp1  endp
  823.  
  824. ;--------------------------------------------------------------
  825. ; songp2 (special = 6)
  826. ; inte processing of position 2nd byte
  827. ; local call with intval in AL
  828. ;
  829. songp2  proc    near
  830.         nop                     ; dummy routine
  831.         mov     ax,0            ; clear special
  832.         mov     special,ax
  833.         ret
  834. songp2  endp
  835.  
  836. ;--------------------------------------------------------------
  837. ; a little beep on the speaker
  838. ;
  839.         public  _beep
  840. _beep   proc    far
  841.  
  842.         mov     al,0b6h
  843.         out     043h,al         ;write timer mode regester
  844.         mov     ax,1000         ;set divisor value to 1000
  845.         out     042h,al         ;write timer 1 count lsb
  846.         mov     al,ah
  847.         out     042h,al         ;write timer 2 count msb
  848.         in      al,061h         ;get current port b setting
  849.         mov     ah,al           ;save current setting.
  850.         or      al,3            ;turn speaker on
  851.         out     061h,al
  852.         mov     cx,0a48h        ;10 msec delay on ibm pc 4.7mh 8088
  853. delay:
  854.         loop    delay
  855.         mov     al,ah           ;get old port b setting
  856.         out     061h,al         ;set it back the way you found it
  857.         ret
  858.         
  859. _beep   endp
  860.  
  861. ;--------------------------------------------------------------
  862. ; blip(char) -- sends char to upper right corner of screen
  863. ;
  864.         public  _blip
  865. _blip   proc    far
  866.         push    bp
  867.         mov     bp,sp
  868.  
  869.         mov     ax,[bp+p1]
  870.         add     ax,'0'
  871.         mov     cx,ds
  872.         mov     dx,0B800H
  873.         mov     ds,dx
  874.         mov     byte ptr ds:9EH,al
  875.         mov     ds,cx
  876.  
  877.         mov     sp,bp
  878.         pop     bp
  879.         ret
  880. _blip   endp
  881.  
  882. ;--------------------------------------------------------------
  883. PRIM_TEXT      ENDS
  884. END
  885.  
  886. ###############################################################
  887.  
  888. /**************************************************************
  889.  *  mpu.h
  890.  *
  891.  *  equates for mpu & tx816
  892.  *
  893.  */
  894.  
  895. /* mpu port addresses & flags
  896.  */
  897. #define MDATA               0x330  /* mpu data port address */
  898. #define MSTAT               0x331  /* mpu status port address */
  899. #define MCMD                0x331  /* mpu command port address */
  900. #define MDSR                0x80   /* mpu data set ready, active low */
  901. #define MDRR                0x40   /* mpu data read ready, active low */
  902.  
  903. /* mpu data codes
  904.  */
  905. #define NULINT              0xFA   /* null interrupt code */
  906. #define MPUACK              0xFE   /* mpu acknowledge */   
  907.  
  908. /* mpu command codes
  909.  */
  910. #define METRONOME_ON       0x83  /*  metronome on with no accents  */
  911. #define METRONOME_ACCENT   0x85  /*  metronome on with accents  */
  912. #define METRONOME_OFF      0x84  /*  metronome off */
  913. #define RESET              0xFF  /*  reset mpuw  */
  914. #define SEND_SYS           0xDF  /*  want to send system message */             
  915. #define EXCL_ON         0x97    /*  exclusive to host: on */
  916. #define EXCL_OFF        0x96    /*  exclusive to host: off */
  917. #define CLOCK_ON        0x95    /*  clock to host: on */
  918. #define CLOCK_OFF       0x94    /*  clock to host: off */
  919.  
  920. /*  midi codes
  921.  */
  922. #define EOX             0xF7    /*  end of transmission */
  923.  
  924. /*  Yamaha specific codes
  925.  */
  926. #define DUMP_1V         0       /*  bulk dump 1 voice */
  927. #define DUMP_1P         1       /*  bulk dump 1 performance setup */
  928. #define DUMP_64P        2       /*  bulk dump 64 performance setups */
  929. #define DUMP_32V        9       /*  bulk dump 32 voices */
  930. #define DUMP_CA         0       /*  dump condition acknowledge */
  931.  
  932. ###############################################################
  933.  
  934. /**************************************************************
  935.  *  testmpu.c
  936.  *
  937.  *  test program for mpu & TX816
  938.  *
  939.  */
  940.  
  941. #include "stdio.h"
  942. #include "mpu.h"
  943.  
  944. /**************************************************************
  945.  *  global values
  946.  */
  947. extern unsigned char tbuf[];        /*  track buffer */
  948. extern unsigned char pbuf[];        /*  parameter buffer */
  949. extern unsigned int indext;         /*  track buf index  */
  950. extern unsigned int indexp;         /*  para buf index */
  951. extern unsigned int channel;        /*  current midi channel */
  952. extern unsigned int rtmsg;          /*  real time message flag */
  953. extern unsigned int pending;        /*  number of sys excl pending */
  954. extern unsigned int recording;      /*  nz when recording track data */
  955. extern unsigned int playing;        /*  nz when playing track data */
  956. extern unsigned int loading;        /*  nz when loading para data */
  957. extern unsigned int enderr;         /*  nz if put index at limit */
  958.  
  959. main(argc, argv)
  960. int argc;
  961. char *argv[];
  962. {
  963.     int i;
  964.  
  965.     initm();
  966.     mpucmd(RESET);
  967.     mpucmd(EXCL_ON);
  968.     mpucmd(CLOCK_ON);
  969.  
  970.     getchar();
  971.     printf("dump in progress\n");
  972.     dump_request(DUMP_1V);
  973.     for(i = 0; i < 256; ++i)
  974.         printf("%x ",pbuf[i]);  
  975.     printf("\n\n");
  976.     mpucmd(RESET);
  977.     printf("reset\n");
  978.     getchar();
  979.     mpucmd(CLOCK_OFF);
  980.     exitm();
  981.     exit(0);
  982. }
  983.  
  984. /**************************************************************
  985.  *    issue a request to dump data
  986.  *  specific to Yamaha
  987.  */
  988. dump_request(fmt)
  989. int fmt;
  990. {
  991.     indexp = 0;
  992.     mpucmd(SEND_SYS);
  993.     mpuput(0xF0);
  994.     mpuput(0x43);
  995.     mpuput(0x20 | channel);
  996.     mpuput(fmt);
  997.     mpuput(EOX);
  998.     while(!loading); 
  999.     beep();
  1000. }
  1001.  
  1002. ###############################################################
  1003.  
  1004.         PAGE    60,127
  1005.         TITLE   MIDI primitives for dumb-MPU
  1006.         NAME    MIDI
  1007.         .SALL
  1008. ;==============================================================
  1009. ; COPYRIGHT (C) 1986 John Dunn
  1010. ;--------------------------------------------------------------
  1011. ; date:        01/02/86
  1012. ; update:      01/02/86
  1013. ; last hacker: John Dunn
  1014. ;==============================================================
  1015. PRIM_TEXT       SEGMENT  BYTE PUBLIC 'CODE'
  1016. PRIM_TEXT       ENDS
  1017. CONST   SEGMENT  WORD PUBLIC 'CONST'
  1018. CONST   ENDS
  1019. _BSS    SEGMENT  WORD PUBLIC 'BSS'
  1020. _BSS    ENDS
  1021. _DATA   SEGMENT  WORD PUBLIC 'DATA'
  1022. _DATA   ENDS
  1023. DGROUP  GROUP   CONST,  _BSS,   _DATA
  1024. ;==============================================================
  1025. _DATA   SEGMENT  WORD PUBLIC 'DATA'
  1026. ;--------------------------------------------------------------
  1027.         PUBLIC  _indexp,_indext,_channel,_rtmsg,_pending
  1028.         PUBLIC  _recording,_playing,_loading,_enderr
  1029. ;--------------------------------------------------------------
  1030. _channel dw     0               ; current midi channel
  1031. _rtmsg  dw      0               ; real time message flag
  1032. _pending dw     0               ; number of sys excl pending
  1033. _recording dw   0               ; nz when recording track data
  1034. _playing dw     0               ; nz when playing track data
  1035. _loading dw     0               ; nz when loading para data       
  1036. _enderr dw      0               ; nz if put index at limit
  1037. _indext dw      0               ; index track buffer
  1038. _indexp dw      0               ; index param buffer
  1039. startt  dw      0               ; start track buffer
  1040. startp  dw      0               ; start param buffer
  1041. endtrk  dw      0               ; end track buffer
  1042. endpar  dw      0               ; end param buffer
  1043. limitt  dw      tbufx-_tbuf     ; track buffer limit
  1044. limitp  dw      pbufx-_pbuf     ; param buffer limit
  1045.  
  1046. icount  dw      0               ; midi msg count index
  1047. rcount  dw      0               ; midi msg run count
  1048. pcount  dw      0               ; play track count
  1049.  
  1050. clkblp  dw      0               ; clock blip count
  1051.  
  1052. intval dw       0               ; inte data value
  1053. special dw      0               ; nz = special routine
  1054. sptable dw      dotimev,procsm,sysexc,songsel,songp1,songp2
  1055.  
  1056. ;--------------------------------------------------------------
  1057. _DATA   ENDS
  1058. ;==============================================================
  1059. PBUF_DATA   SEGMENT PARA MEMORY 'BUFFER'
  1060. ;--------------------------------------------------------------
  1061.         PUBLIC  _pbuf
  1062. ;--------------------------------------------------------------
  1063. _pbuf   db      17000 dup(?)     ; parameter buffer
  1064. pbufx   db      0
  1065. ;--------------------------------------------------------------
  1066. PBUF_DATA   ENDS
  1067. ;==============================================================
  1068. TBUF_DATA   SEGMENT PARA MEMORY 'BUFFER'
  1069. ;--------------------------------------------------------------
  1070.         PUBLIC  _tbuf
  1071. ;--------------------------------------------------------------
  1072. _tbuf  db      16384 dup(?)     ; parameter buffer
  1073. tbufx  db      0
  1074. ;--------------------------------------------------------------
  1075. TBUF_DATA   ENDS
  1076. ;==============================================================
  1077. PRIM_TEXT      SEGMENT
  1078.         ASSUME  CS: PRIM_TEXT, DS: DGROUP, SS: DGROUP, ES: DGROUP
  1079. ;==============================================================
  1080. bpo     equ 6           ; base pointer offset
  1081.                                 ; 6 = large model; 4 = small
  1082. p1      equ bpo                 ; single word arg 1, use [bp+@1]
  1083. p2      equ bpo+2       ; single word arg 2, use [bp+@2]
  1084. ;--------------------------------------------------------------
  1085. mdata  equ 0330H               ; mpu data port address
  1086. mstat  equ 0331H               ; mpu status port address
  1087. mcmd   equ 0331H               ; mpu command port address
  1088. mdsr   equ 80H                 ; mpu data set ready, active low
  1089. mdrr   equ 40H                 ; mpu data read ready, active low
  1090. ;--------------------------------------------------------------
  1091. ; initialize mpu, int vectors, etc.
  1092. ; must be called once only on startup
  1093. ;
  1094.         public  _initm
  1095. _initm  proc    far
  1096.         push    es              ; save current es
  1097.         mov     ah,35h          ; get current int 2
  1098.         mov     al,0AH
  1099.         int     21H
  1100.         mov     word ptr cs:orgint+3,es        ; save it
  1101.         mov     word ptr cs:orgint+1,bx
  1102.         pop     es              ; restore es
  1103.  
  1104.         push    ds              ; save current ds
  1105.         mov     ah,25H          ; set int vect
  1106.         mov     al,0AH          ; int 2 for MPU
  1107.         mov     dx,seg mpuint
  1108.         mov     ds,dx
  1109.         mov     dx,offset mpuint
  1110.         int     21H             ; set new int vect
  1111.         pop     ds              ; restore ds
  1112.  
  1113.         call    mpurst          ; reset mpu
  1114.         in      al,21H          ; enable irq2
  1115.         jmp     short $+2       ; delay for AT 
  1116.         and     al,0FBH
  1117.         out     21H,al
  1118.         ret
  1119. _initm  endp                     ; end of init mpu
  1120.  
  1121. ;--------------------------------------------------------------
  1122. ; shutdown mpu, restore int vectors, etc.
  1123. ; must be called once only on exit
  1124. ;
  1125.         public  _exitm
  1126. _exitm  proc    far
  1127.         in      al,21H          ; disable irq2
  1128.         jmp     short $+2       ; delay for AT 
  1129.         or      al,4
  1130.         out     21H,al
  1131.  
  1132.         push    ds
  1133.         mov     ah,25h          ; restore previous irq2
  1134.         mov     al,0AH
  1135.         mov     dx,word ptr cs:orgint+3
  1136.         mov     ds,dx
  1137.         mov     dx,word ptr cs:orgint+1
  1138.         int     21h
  1139.         pop     ds
  1140.         ret
  1141. _exitm  endp
  1142.  
  1143. ;--------------------------------------------------------------
  1144. ; mpurst
  1145. ; reset the mpu
  1146. ; local call
  1147. ;
  1148. mpurst  proc    near
  1149.         cli                     ; disable intes
  1150.         mov     dx,mstat        ; mpu status port
  1151. mpurs1: in      al,dx           ; get the status
  1152.         and     al,mdrr         ; test for Data Recieve Ready
  1153.         jnz     mpurs1          ; loop til ready
  1154.         mov     ax,0FFH         ; get the command
  1155.         out     dx,al           ; send to mpu
  1156. mpurs2: in      al,dx           ; get the status
  1157.         and     al,mdsr         ; test for Data Set Ready
  1158.         jnz     mpurs2          ; loop til ready
  1159.         mov     dx,mdata        ; read mpu data port
  1160.         mov     dx,mdata        ; read mpu data port
  1161.         mov     dx,mdata        ; read mpu data port
  1162.         sti                     ; enable intes
  1163.         ret                     ; exit
  1164. mpurst  endp
  1165.  
  1166. ;--------------------------------------------------------------
  1167. ; this routine is only called by int 2
  1168. ; if it was not generated by the mpu, it vectors
  1169. ; to the original int address, otherwise it saves
  1170. ; registers, then calls the c routine _mpuint,
  1171. ; after which it restores registers, clears nmi
  1172. ; and returns from int. 
  1173. ;
  1174. mpuint  proc    far
  1175.         push    ax              ; save ax
  1176.         push    dx
  1177.         mov     dx,mstat        ; read mpu status
  1178. mpui0:  jmp     short $+2
  1179.         in      al,dx
  1180.         and     al,mdsr         ; generated by mpu?
  1181.         jz      mpui1           ; yes, branch
  1182.         pop     dx              ; no, restore cpu
  1183.         pop     ax
  1184.         iret                    ; return from interrupt
  1185. orgint: jmp     far ptr intval  ; dummy vector, filled by _initm
  1186.         dw      0
  1187.  
  1188. mpui1:
  1189.         push    bx              ; save cpu state
  1190.         push    cx
  1191.         push    di
  1192.         push    si
  1193.         push    bp
  1194.         push    ds
  1195.         push    es
  1196.  
  1197.         mov     ax,seg dgroup   ; set up c seg regs
  1198.         mov     ds,ax
  1199.         mov     es,ax
  1200.  
  1201.         mov     dx,mdata        ; get mpu int data
  1202.         in      al,dx
  1203.  
  1204.         call    dompu           ; do the mpu routine
  1205.  
  1206.         pop     es              ; restore seg regs
  1207.         pop     ds
  1208.         pop     bp              ; restore cpu state
  1209.         pop     si
  1210.         pop     di
  1211.         pop     cx
  1212.         pop     bx
  1213.         pop     dx
  1214.         mov     al,20H          ; send eoi to 8259
  1215.         out     20H,al
  1216.         pop     ax
  1217.         iret                    ; return from interrupt
  1218. mpuint  endp
  1219.  
  1220.  
  1221. ;--------------------------------------------------------------
  1222. ; dompu
  1223. ; process mpu inte
  1224. ; local call
  1225. ;
  1226. dompu   proc    near
  1227.         mov     byte ptr intval,al ; save as global variable
  1228.         mov     bx,special
  1229.         or      bx,bx           ; special flag set?
  1230.         jz      dompu1          ; no, branch
  1231.         dec     bx              ; yes, jump to special routine
  1232.         add     bx,bx
  1233.         mov     dx,sptable[bx]
  1234.         jmp     dx
  1235. dompu1: cmp     al,0F0H         ; < F0H
  1236.         jnb     dompu2          ; no, branch
  1237.         jmp     timev           ; yes, do time value
  1238. dompu2: cmp     al,0F8H         ; < F8H
  1239.         jnb     dompu3          ; no, branch
  1240.         jmp     trackd          ; yes, do track data request
  1241. dompu3: jnz     dompu4          ; branch if not = F8H
  1242.         jmp     timeo           ; else do timing overflow
  1243. dompu4: cmp     al,0F9H         ; = F9?
  1244.         jnz     dompu5          ; no, branch
  1245.         jmp     condr           ; yes, do conductor request
  1246. dompu5: cmp     al,0FDH         ; = FD?
  1247.         jnz     dompu6          ; no, branch
  1248.         jmp     clockh          ; yes, do clock to host
  1249. dompu6: cmp     al,0FCH         ; = FD?
  1250.         jnz     dompu7          ; no, branch
  1251.         jmp     allend          ; yes, do all end
  1252. dompu7: cmp     al,0FFH         ; = FF?
  1253.         jnz     dompu8          ; no, branch
  1254.         jmp     midism          ; yes, do midi system message
  1255. dompu8: ret
  1256. dompu   endp
  1257.  
  1258. ;--------------------------------------------------------------
  1259. ; mpuput(data)
  1260. ; send data to mpu-401
  1261. ; C call
  1262. ;
  1263.         public  _mpuput
  1264. _mpuput proc    far
  1265.         push    bp
  1266.         mov     bp,sp
  1267.  
  1268.         mov     dx,mstat        ; mpu status port
  1269. mpup1:  in      al,dx           ; get the status
  1270.         and     al,mdrr         ; test for Data Recieve Ready
  1271.         jnz     mpup1           ; loop til ready
  1272.         mov     dx,mdata        ; mpu data port
  1273.         mov     ax,[bp+p1]      ; get the data
  1274.         out     dx,al           ; send to mpu
  1275.  
  1276.         mov     sp,bp           ; restore C sp
  1277.         pop     bp
  1278.         ret                     ; exit
  1279. _mpuput endp
  1280.  
  1281. ;--------------------------------------------------------------
  1282. ; mpuput
  1283. ; send data in AL to mpu-401
  1284. ; local call, AX is preserved
  1285. ;
  1286. mpuput  proc    near
  1287.     push    ax
  1288.         mov     dx,mstat        ; mpu status port
  1289. mpupa1: in      al,dx           ; get the status
  1290.         and     al,mdrr         ; test for Data Recieve Ready
  1291.         jnz     mpupa1          ; loop til ready
  1292.         mov     dx,mdata        ; mpu data port
  1293.         pop     ax              ; get the data
  1294.         out     dx,al           ; send to mpu
  1295.         ret                     ; exit
  1296. mpuput  endp
  1297.  
  1298. ;--------------------------------------------------------------
  1299. ; data=mpuget()
  1300. ; get data from mpu-401
  1301. ; C call
  1302. ;
  1303.         public  _mpuget
  1304. _mpuget proc    far
  1305.  
  1306.         mov     dx,mstat        ; mpu status port
  1307. mpug1:  in      al,dx           ; get the status
  1308.         and     al,mdsr         ; test for Data Set Ready
  1309.         jnz     mpug1           ; loop til ready
  1310.         mov     dx,mdata        ; mpu data port
  1311.         in      al,dx           ; get the data byte
  1312.         mov     ah,0            ; zero out ms byte
  1313.         ret                     ; exit with ax = data
  1314. _mpuget endp
  1315.  
  1316. ;--------------------------------------------------------------
  1317. ; mpuget
  1318. ; get data from mpu-401 to AX
  1319. ; local call
  1320. ;
  1321. mpuget  proc    near
  1322.         mov     dx,mstat        ; mpu status port
  1323. mpuga1: in      al,dx           ; get the status
  1324.         and     al,mdsr         ; test for Data Set Ready
  1325.         jnz     mpuga1          ; loop til ready
  1326.         mov     dx,mdata        ; mpu data port
  1327.         in      al,dx           ; get the data byte
  1328.         mov     ah,0            ; zero out ms byte
  1329.         ret                     ; exit with ax = data
  1330. mpuget  endp
  1331.  
  1332. ;--------------------------------------------------------------
  1333. ; mpucmd(cmd)
  1334. ; send a command to mpu-401
  1335. ;
  1336.         public  _mpucmd
  1337. _mpucmd proc    far
  1338.         push    bp
  1339.         mov     bp,sp
  1340.  
  1341.         mov     dx,mstat        ; mpu status port
  1342. mpuc1:  in      al,dx           ; get the status
  1343.         and     al,mdrr         ; test for Data Recieve Ready
  1344.         jnz     mpuc1           ; loop til ready
  1345.         cli                     ; disable intes
  1346.         mov     ax,[bp+p1]      ; get the command
  1347.         out     dx,al           ; send to mpu
  1348. mpuc2:  in      al,dx           ; get the status
  1349.         and     al,mdsr         ; test for Data Set Ready
  1350.         jnz     mpuc2           ; loop til ready
  1351.         mov     dx,mdata        ; mpu data port
  1352.         in      al,dx           ; read it
  1353.         cmp     al,0FEH         ; acknowledge?
  1354.         jz      mpuc3           ; yes, branch
  1355.  
  1356.         push    di              ; save C registers
  1357.         push    si
  1358.         call    dompu           ; do mpu routine
  1359.         pop     si
  1360.         pop     di
  1361.         mov     dx,mstat        ; mpu status port
  1362.         jmp     short mpuc2     ; check again for ack
  1363.  
  1364. mpuc3:  sti                     ; enable ints
  1365.         mov     sp,bp           ; restore C sp
  1366.         pop     bp
  1367.         ret                     ; exit
  1368. _mpucmd endp
  1369.  
  1370. ;--------------------------------------------------------------
  1371. ; data = gett()
  1372. ; get byte from track buffer
  1373. ; C call
  1374. ;
  1375.         public  _gett
  1376. _gett   proc    far
  1377.         mov     bx,_indext      ; get index
  1378.         mov     dx,seg _tbuf
  1379.         push    ds
  1380.         mov     ds,dx           ; fetch the data
  1381.         mov     al,ds:[bx]
  1382.         xor     ah,ah           ; ax = data
  1383.         pop     ds
  1384.         inc     bx              ; inc index
  1385.         cmp     bx,endtrk       ; reached end?
  1386.         jnz     gett1           ; no, exit
  1387.         mov     bx,startt       ; yes, set index = start
  1388. gett1:  mov     _indext,bx      ; save index
  1389.         ret                     ; exit with ax = data
  1390. _gett   endp
  1391.  
  1392. ;--------------------------------------------------------------
  1393. ; gett
  1394. ; get byte to AX from track buffer
  1395. ; local call
  1396. ;
  1397. gett    proc    near
  1398.         mov     bx,_indext      ; get index
  1399.         mov     dx,seg _tbuf
  1400.         push    ds
  1401.         mov     ds,dx           ; fetch the data
  1402.         mov     al,ds:[bx]
  1403.         xor     ah,ah           ; ax = data
  1404.         pop     ds
  1405.         inc     bx              ; inc index
  1406.         cmp     bx,endtrk       ; reached end?
  1407.         jnz     getta1          ; no, exit
  1408.         mov     bx,startt       ; yes, set index = start
  1409. getta1: mov     _indext,bx      ; save index
  1410.         ret                     ; exit with ax = data
  1411. gett   endp
  1412.  
  1413. ;--------------------------------------------------------------
  1414. ; putt(track_data)
  1415. ; put byte to track buffer
  1416. ; C call
  1417. ;
  1418.         public  _putt
  1419. _putt   proc    far
  1420.         push    bp
  1421.         mov     bp,sp
  1422.         mov     bx,_indext      ; get index
  1423.         mov     dx,seg _tbuf
  1424.         mov     al,[bp+p1]      ; get the data
  1425.         push    ds
  1426.         mov     ds,dx           ; store the data
  1427.         mov     ds:[bx],al
  1428.         pop     ds
  1429.         inc     bx              ; inc index
  1430.         cmp     bx,limitt       ; reached limit?
  1431.         mov     ax,1            ; flag error
  1432.         jz      putt0           ; yes, branch with err
  1433.         mov     ax,0            ; no, flag no-error
  1434.         mov     _indext,bx      ; store index
  1435.         mov     endtrk,bx       ; end = index
  1436. putt0:  mov     _enderr,ax      ; save in _enderr
  1437.         mov     sp,bp           ; restore C sp
  1438.         pop     bp
  1439.         ret                     ; exit
  1440. _putt   endp
  1441.  
  1442. ;--------------------------------------------------------------
  1443. ; putt
  1444. ; put byte in AL to track buffer
  1445. ; local call
  1446. ;
  1447. putt    proc    near
  1448.         mov     bx,_indext      ; get index
  1449.         mov     dx,seg _tbuf
  1450.         push    ds
  1451.         mov     ds,dx           ; store the data
  1452.         mov     ds:[bx],al
  1453.         pop     ds
  1454.         inc     bx              ; inc index
  1455.         cmp     bx,limitt       ; reached limit?
  1456.         mov     ax,1            ; flag error
  1457.         jz      putta0          ; yes, branch with err
  1458.         mov     ax,0            ; no, flag no-error
  1459.         mov     _indext,bx      ; store index
  1460.         mov     endtrk,bx       ; end = index
  1461. putta0: mov     _enderr,ax      ; save in _enderr
  1462.         ret                     ; exit
  1463. putt    endp
  1464.  
  1465. ;--------------------------------------------------------------
  1466. ; data = getp()
  1467. ; get byte from parameter buffer
  1468. ; C call
  1469. ;
  1470.         public  _getp
  1471. _getp   proc    far
  1472.         mov     bx,_indexp      ; get index
  1473.         mov     dx,seg _pbuf
  1474.         push    ds
  1475.         mov     ds,dx           ; fetch the data
  1476.         mov     al,ds:[bx]
  1477.         xor     ah,ah           ; ax = data
  1478.         pop     ds
  1479.         inc     bx              ; inc index
  1480.         cmp     bx,endpar       ; reached end?
  1481.         jnz     getp1           ; no, exit
  1482.         mov     bx,startp       ; yes, set index = start
  1483. getp1:  mov     _indexp,bx      ; save index
  1484.         ret                     ; exit with ax = data
  1485. _getp   endp
  1486.  
  1487. ;--------------------------------------------------------------
  1488. ; getp
  1489. ; get byte to AX from param buffer
  1490. ; local call
  1491. ;
  1492. getp    proc    near
  1493.         mov     bx,_indexp      ; get index
  1494.         mov     dx,seg _pbuf
  1495.         push    ds
  1496.         mov     ds,dx           ; fetch the data
  1497.         mov     al,ds:[bx]
  1498.         xor     ah,ah           ; ax = data
  1499.         pop     ds
  1500.         inc     bx              ; inc index
  1501.         cmp     bx,endpar       ; reached end?
  1502.         jnz     getpa1          ; no, exit
  1503.         mov     bx,startp       ; yes, set index = start
  1504. getpa1: mov     _indexp,bx      ; save index
  1505.         ret                     ; exit with ax = data
  1506. getp   endp
  1507.  
  1508. ;--------------------------------------------------------------
  1509. ; putp(param_data)
  1510. ; put byte to param buffer
  1511. ; C call
  1512. ;
  1513.         public  _putp
  1514. _putp   proc    far
  1515.         push    bp
  1516.         mov     bp,sp
  1517.         mov     bx,_indexp      ; get index
  1518.         mov     dx,seg _pbuf
  1519.         mov     al,[bp+p1]      ; get the data
  1520.         push    ds
  1521.         mov     ds,dx           ; store the data
  1522.         mov     ds:[bx],al
  1523.         pop     ds
  1524.         inc     bx              ; inc index
  1525.         cmp     bx,limitp       ; reached limit?
  1526.         mov     ax,1            ; flag error
  1527.         jz      putp0           ; yes, branch with err
  1528.         mov     ax,0            ; no, flag no-error
  1529.         mov     _indexp,bx      ; store index
  1530.         mov     endpar,bx       ; end = index
  1531. putp0:  mov     _enderr,ax      ; save in _enderr
  1532.         mov     sp,bp           ; restore C sp
  1533.         pop     bp
  1534.         ret                     ; exit
  1535. _putp   endp
  1536.  
  1537. ;--------------------------------------------------------------
  1538. ; putp
  1539. ; put byte in AL to param buffer
  1540. ; local call
  1541. ;
  1542. putp    proc    near
  1543.         mov     bx,_indexp      ; get index
  1544.         mov     dx,seg _pbuf
  1545.         push    ds
  1546.         mov     ds,dx           ; store the data
  1547.         mov     ds:[bx],al
  1548.         pop     ds
  1549.         inc     bx              ; inc index
  1550.         cmp     bx,limitp       ; reached limit?
  1551.         mov     ax,1            ; flag error
  1552.         jz      putpa0          ; yes, branch with err
  1553.         mov     ax,0            ; no, flag no-error
  1554.         mov     _indexp,bx      ; store index
  1555.         mov     endpar,bx       ; end = index
  1556. putpa0: mov     _enderr,ax      ; save in _enderr
  1557.         ret                     ; exit
  1558. putp    endp
  1559.  
  1560. ;--------------------------------------------------------------
  1561. ; timeo
  1562. ; process timing overflow on inte
  1563. ; local call with intval in AL
  1564. ;
  1565. timeo   proc    near
  1566.         call    putt
  1567.         ret
  1568. timeo   endp
  1569.  
  1570. ;--------------------------------------------------------------
  1571. ; condr
  1572. ; process conductor request on inte
  1573. ; local dummy routine, sends timing overflow byte
  1574. ;
  1575. condr   proc    near
  1576.         mov     al,0F8H
  1577.         call    putt
  1578.         ret
  1579. condr   endp
  1580.  
  1581. ;--------------------------------------------------------------
  1582. ; clockh
  1583. ; process clock to host on inte
  1584. ; local call 
  1585. ;
  1586. clockh  proc    near
  1587.         mov     ax,clkblp       ; get blip flag
  1588.         inc     ax              ; count up
  1589.         and     ax,1
  1590.         mov     clkblp,ax       ; put back
  1591.         inc     ax              ; 1,2 = happy face
  1592.         mov     cx,ds
  1593.         mov     dx,0B800H       ; point to gx screen
  1594.         mov     ds,dx
  1595.         mov     byte ptr ds:9EH,al ; display blip
  1596.         mov     ds,cx
  1597.         ret
  1598. clockh  endp
  1599.  
  1600. ;--------------------------------------------------------------
  1601. ; allend
  1602. ; process all end on inte
  1603. ; local call, clears playing flag
  1604. ;
  1605. allend  proc    near
  1606.         mov     ax,0
  1607.         mov     _playing,ax
  1608.         ret
  1609. allend  endp
  1610.  
  1611. ;--------------------------------------------------------------
  1612. ; timev
  1613. ; process time value on inte
  1614. ; local call with intval in AL
  1615. ;
  1616. timev   proc    near
  1617.         call    putt
  1618.         mov     ax,1            ; set special = 1
  1619.         mov     special,ax      ; dotimev on next inte
  1620.         ret
  1621. timev   endp
  1622.  
  1623. ;--------------------------------------------------------------
  1624. ; dotimev (special = 1 )
  1625. ; next inte processing of time value
  1626. ; local call with intval in AL
  1627. ;
  1628. dotimev proc    near
  1629.         cmp     al,0F8H         ; mpu mark, no operation
  1630.         jz      dotime1
  1631.         cmp     al,0F9H         ; mpu mark, measure end
  1632.         jz      dotime2
  1633.         cmp     al,0FCH         ; mpu mark, data end
  1634.         jnz     dotime3
  1635.         mov     ax,0
  1636.         mov     _recording,ax   ; clr recording flag
  1637. dotime2:call    putt            ; put in record buffer
  1638. dotime1:mov     ax,0
  1639.         mov     special,ax      ; done, clear special
  1640.         ret                     ; exit
  1641. dotime3:mov     ah,al           ; get a copy
  1642.         and     ah,0F0H         ; zip channel data
  1643.         cmp     ah,0C0H         ; midi msg, program change
  1644.         jz      dotime4
  1645.         cmp     ah,0DH          ; midi msg, channel pressure
  1646.         jnz     dotime5
  1647. dotime4:mov     dx,1            ; set to recieve 1 more byte
  1648.         jmp     short dotime6
  1649. dotime5:cmp     ah,80H          ; midi msg, note off
  1650.         jz      dotime7
  1651.         cmp     ah,90H          ; midi msg, note on
  1652.         jz      dotime7
  1653.         cmp     ah,0A0H         ; midi msg, after touch
  1654.         jz      dotime7
  1655.         cmp     ah,0B0H         ; midi msg, control change
  1656.         jz      dotime7
  1657.         cmp     ah,0E0H         ; midi msg, pitch wheel
  1658.         jnz     dotime8
  1659. dotime7:mov     dx,2            ; set to recieve 2 more bytes
  1660. dotime6:mov     rcount,dx
  1661.         mov     icount,dx
  1662.         call    putt            ; put in record buffer
  1663.         ret                     ; exit
  1664. dotime8:and     ah,80H          ; < 7FH ?
  1665.         jz      dotime9         ; yes, branch
  1666.         mov     ax,0            ; no, is error
  1667.         mov     special,ax      ; clear special
  1668.         call    far ptr _beep   ; signal error
  1669.         ret                     ; exit
  1670. dotime9:mov     ah,byte ptr icount ; get current count
  1671.         cmp     ah,0            ; new one?
  1672.         jnz     dotim10         ; no, branch
  1673.         mov     ah,byte ptr rcount ; yes, icount <-- rcount
  1674. dotim10:push    ax              ; save it
  1675.         call    putt            ; save the data byte in AL
  1676.         pop     ax              ; ah = icount
  1677.         dec     ah              ; dec icount
  1678.         mov     byte ptr icount,ah ; save it
  1679.         jnz     dotime11        ; branch if icount not 0
  1680.         mov     ax,0            ; else clear special
  1681.         mov     special,ax
  1682. dotime11:ret                    ; exit
  1683. dotimev endp
  1684.  
  1685. ;--------------------------------------------------------------
  1686. ; trackd
  1687. ; process track play request on inte
  1688. ; local call with intval in AL
  1689. ;
  1690. trackd  proc    near
  1691.         call    gett            ; get next track buffer byte
  1692.         nop                     ; fix midi channel
  1693.         call    mpuput          ; send it to mpu data port
  1694.         cmp     al,0F8H         ; midi timing overflow
  1695.         jnz     trackd1
  1696.         ret                     ; just exit if it was timing overfow
  1697. trackd1:call    gett            ; get next track buffer byte
  1698.         nop                     ; fix midi channel
  1699.         call    mpuput          ; send it to mpu data port
  1700.         and     al,0F0H         ; strip midi channel info
  1701.         cmp     al,0F0H         ; mpu mark
  1702.         jnz     trackd2
  1703.         ret
  1704. trackd2:test    al,80H          ; <= 7FH ?
  1705.         jnz     trackd3         ; no, branch
  1706.         cmp     pcount,1        ; pcount = 1 ?
  1707.         jnz     trackd4         ; no, branch
  1708.         ret                     ; yes, exit
  1709. trackd3:cmp     al,0C0H         ; one byte needed?
  1710.         jz      trackd5
  1711.         cmp     al,0D0H
  1712.         jnz     trackd6
  1713. trackd5:mov     pcount,1        ; yes, set running pcount to 1
  1714.         jmp     short trackd4   ; ... and get one more byte 
  1715. trackd6:mov     pcount,2        ; else set running pcount to 2
  1716.         call    gett            ; get next track buffer byte
  1717.         nop                     ; fix midi channel
  1718.         call    mpuput          ; send it to mpu data port
  1719. trackd4:call    gett            ; get next track buffer byte
  1720.         nop                     ; fix midi channel
  1721.         call    mpuput          ; send it to mpu data port
  1722.         ret
  1723. trackd  endp
  1724.  
  1725. ;--------------------------------------------------------------
  1726. ; midism
  1727. ; process midi system message on inte
  1728. ; local call
  1729. ;
  1730. midism  proc    near
  1731.         mov     ax,2            ; flag special = 2
  1732.         mov     special,ax      ; procsm on next inte
  1733.         ret
  1734. midism  endp
  1735.  
  1736. ;--------------------------------------------------------------
  1737. ; procsm ( special = 2)
  1738. ; continue to process midi system message in inte
  1739. ; local call with intval in AL
  1740. ;
  1741. procsm  proc    near
  1742.         cmp     al,0F0H         ; midi exclusive
  1743.         jnz     procsm1
  1744.         call    putp            ; save in para buffer
  1745.         mov     ax,1            ; set loading flag
  1746.         mov     _loading,ax
  1747.         mov     ax,3            ; set special = 3
  1748.         mov     special,ax      ; continue on next inte
  1749.         ret
  1750. procsm1:cmp     al,0F3H         ; song select
  1751.         jnz     procsm2
  1752.         mov     ax,4            ; set special = 4
  1753.         mov     special,ax      ; continue on next inte
  1754.         ret
  1755. procsm2:cmp     al,0F2H         ; song position
  1756.         jnz     procsm3
  1757.         mov     ax,5            ; set special = 5
  1758.         mov     special,ax      ; continue on next inte
  1759.         ret
  1760. procsm3:cmp     al,0F6H         ; tune request
  1761.         jnz     procsm4
  1762.         nop                     ; insert routine here
  1763.         jmp     short procsm0   ; clr special & exit     
  1764. procsm4:mov     byte ptr _rtmsg,al ; flag real time message
  1765. procsm0:mov     ax,0            ; clear special
  1766.         mov     special,ax
  1767.         ret                     ; exit        
  1768. procsm  endp
  1769.  
  1770. ;--------------------------------------------------------------
  1771. ; sysexc (special = 3 )
  1772. ; inte processing of system exclusive values
  1773. ; local call with intval in AL
  1774. ;
  1775. sysexc  proc    near
  1776.         push    ax              ; save inte value
  1777.         call    putp            ; save in parameter buffer
  1778.         pop     ax
  1779.         cmp     al,0F7H         ; was it EOX
  1780.         jnz     sysexc0         ; no, just exit
  1781.         mov     ax,0            ; yes,
  1782.         mov     _loading,ax     ; clear loading flag
  1783.         mov     special,ax      ; clear special
  1784.         inc     word ptr _pending ; inc pending flag
  1785. sysexc0:ret                     ; exit
  1786. sysexc  endp
  1787.  
  1788. ;--------------------------------------------------------------
  1789. ; songsel (special = 4)
  1790. ; inte processing of song select
  1791. ; local call with intval in AL
  1792. ;
  1793. songsel proc    near
  1794.         nop                     ; dummy routine
  1795.         mov     ax,0            ; clear special
  1796.         mov     special,ax
  1797.         ret
  1798. songsel endp
  1799.  
  1800. ;--------------------------------------------------------------
  1801. ; songp1 (special = 5)
  1802. ; inte processing of song position 1st byte
  1803. ; local call with intval in AL
  1804. ;
  1805. songp1  proc    near
  1806.         nop                     ; dummy routine
  1807.         mov     ax,6            ; special = 6
  1808.         mov     special,ax      ; songp2 on next int
  1809.         ret
  1810. songp1  endp
  1811.  
  1812. ;--------------------------------------------------------------
  1813. ; songp2 (special = 6)
  1814. ; inte processing of position 2nd byte
  1815. ; local call with intval in AL
  1816. ;
  1817. songp2  proc    near
  1818.         nop                     ; dummy routine
  1819.         mov     ax,0            ; clear special
  1820.         mov     special,ax
  1821.         ret
  1822. songp2  endp
  1823.  
  1824. ;--------------------------------------------------------------
  1825. ; a little beep on the speaker
  1826. ;
  1827.         public  _beep
  1828. _beep   proc    far
  1829.  
  1830.         mov     al,0b6h
  1831.         out     043h,al         ;write timer mode regester
  1832.         mov     ax,1000         ;set divisor value to 1000
  1833.         out     042h,al         ;write timer 1 count lsb
  1834.         mov     al,ah
  1835.         out     042h,al         ;write timer 2 count msb
  1836.         in      al,061h         ;get current port b setting
  1837.         mov     ah,al           ;save current setting.
  1838.         or      al,3            ;turn speaker on
  1839.         out     061h,al
  1840.         mov     cx,0a48h        ;10 msec delay on ibm pc 4.7mh 8088
  1841. delay:
  1842.         loop    delay
  1843.         mov     al,ah           ;get old port b setting
  1844.         out     061h,al         ;set it back the way you found it
  1845.         ret
  1846.         
  1847. _beep   endp
  1848.  
  1849. ;--------------------------------------------------------------
  1850. ; blip(char) -- sends char to upper right corner of screen
  1851. ;
  1852.         public  _blip
  1853. _blip   proc    far
  1854.         push    bp
  1855.         mov     bp,sp
  1856.  
  1857.         mov     ax,[bp+p1]
  1858.         add     ax,'0'
  1859.         mov     cx,ds
  1860.         mov     dx,0B800H
  1861.         mov     ds,dx
  1862.         mov     byte ptr ds:9EH,al
  1863.         mov     ds,cx
  1864.  
  1865.         mov     sp,bp
  1866.         pop     bp
  1867.         ret
  1868. _blip   endp
  1869.  
  1870. ;--------------------------------------------------------------
  1871. PRIM_TEXT      ENDS
  1872. END
  1873.  
  1874. ###############################################################
  1875.  
  1876. /**************************************************************
  1877.  *  midi.h
  1878.  *
  1879.  *  equates for MPU-401 & MIDI
  1880.  *
  1881.  */
  1882.  
  1883. /* mpu port addresses & flags
  1884.  */
  1885. #define MDATA               0x330  /* mpu data port address */
  1886. #define MSTAT               0x331  /* mpu status port address */
  1887. #define MCMD                0x331  /* mpu command port address */
  1888. #define MDSR                0x80   /* mpu data set ready, active low */
  1889. #define MDRR                0x40   /* mpu data read ready, active low */
  1890.  
  1891. /*  general equates
  1892.  */
  1893. #define TRUE            1
  1894. #define FALSE           0
  1895.  
  1896. /*  midi codes
  1897.  */
  1898. #define KEY_ON          0x90    /*  +2, turn note on/off */
  1899. #define KEY_OFF         0x80    /*  +2, turn note off */
  1900. #define EOX             0xF7    /*  +0, end of transmission */
  1901.  
  1902. /*  Yamaha specific codes
  1903.  */
  1904. #define DUMP_1V         0       /*  bulk dump 1 voice */
  1905. #define DUMP_1P         1       /*  bulk dump 1 performance setup */
  1906. #define DUMP_64P        2       /*  bulk dump 64 performance setups */
  1907. #define DUMP_32V        9       /*  bulk dump 32 voices */
  1908. #define DUMP_CA         125     /*  dump condition acknowledge */
  1909.  
  1910. ###############################################################
  1911.  
  1912. /**************************************************************
  1913.  *  testmidi.c      1/4/86    Copyright (c) 1986, John Dunn 
  1914.  *
  1915.  *  test program for MPU/MIDI and TX816
  1916.  *
  1917.  */
  1918.  
  1919. #include "stdio.h"
  1920. #include "midi.h"
  1921.  
  1922. /**************************************************************
  1923.  *  global values
  1924.  */
  1925. extern unsigned char pbuf[];        /*  play buffer */
  1926. extern unsigned char rbuf[];        /*  recording buffer */
  1927. extern unsigned char sbuf[];        /*  sysexc dump buffer */
  1928. extern unsigned int indexp;         /*  play buf index  */
  1929. extern unsigned int indexr;         /*  recording buf index  */
  1930. extern unsigned int indexs;         /*  sysexc dump buf index */
  1931. extern unsigned int channel;        /*  current midi channel */
  1932. extern unsigned int pending;        /*  number of sys excl pending */
  1933. extern unsigned int recording;      /*  nz when recording track data */
  1934. extern unsigned int playing;        /*  nz when playing track data */
  1935. extern unsigned int looping;        /*  nz when playing a loop */
  1936. extern unsigned int loading;        /*  nz when loading sysexc dump data */
  1937. extern unsigned int enderr;         /*  nz if put index at limit */
  1938. extern unsigned long ticks;         /*  clock tick count */
  1939. extern unsigned long nextt;         /*  timer tick count */
  1940. extern unsigned char tocks[];       /*  midi string tick representation */
  1941. extern unsigned char packet[];      /*  midi output packet */
  1942.  
  1943. unsigned int gv = 64;               /*  global note velocity */
  1944.  
  1945. main(argc, argv)
  1946. int argc;
  1947. char *argv[];
  1948. {
  1949.     int i;
  1950.     initm();
  1951.     printf("starting\n");
  1952.     getchar();
  1953.     channel = 0;
  1954.     startt();
  1955.     dump_request(DUMP_1V);
  1956.     for(i = 0; i < 166; ++i)
  1957.         printf("%x ",sbuf[i]);  
  1958.     printf("\n\n");
  1959.     for(i = 145+6; i < 155+6; ++i)
  1960.         printf("%c",sbuf[i]);  
  1961.     printf("\n\n");
  1962.     dump_request(DUMP_1P);
  1963.     for(i = 0; i < 110; ++i)
  1964.         printf("%x ",sbuf[i]);  
  1965.     printf("\n\n");
  1966.     for(i = 64+6; i < 94+6; ++i)
  1967.         printf("%c",sbuf[i]);  
  1968.     printf("\n");
  1969.     foo();
  1970.     nextt = 0;
  1971.     ticks = 0;
  1972.     indexp = 0;
  1973.     playing = TRUE;
  1974.     getchar();
  1975.     looping = TRUE;
  1976.     playing = TRUE;
  1977.     getchar();
  1978.     while(!packet[2]);
  1979.     printf("ready to record\n");
  1980.     indexr = 0;
  1981.     recording = 1;
  1982.     getchar();
  1983.     indexr = 0;
  1984.     for(i = 0; i < 256; ++i)
  1985.         printf("%x ",rbuf[i]);  
  1986.     printf("\n\n");
  1987.     stopt();
  1988.     exitm();
  1989.     getchar();
  1990.     exit(0);
  1991. }
  1992.  
  1993. /**************************************************************
  1994.  *    issue a request to dump data
  1995.  *  specific to Yamaha
  1996.  */
  1997. dump_request(fmt)
  1998. int fmt;
  1999. {
  2000.     indexs = 0;
  2001.     midio(0xF0);
  2002.     midio(0x43);
  2003.     midio(0x20 | channel);
  2004.     midio(fmt);
  2005.     midio(EOX);
  2006.     while(!loading); 
  2007. }
  2008.  
  2009. /**************************************************************
  2010.  *    xlates(notes)
  2011.  *  translate a character string to midi data in the play buffer
  2012.  *  valid characters:
  2013.  *      T,S,I,Q,H,W         = notes
  2014.  *      0,1,2,3,4,5,6,7,8,9 = octaves         
  2015.  *      A,B,C,D,E,F,G       = pitch
  2016.  *      +,-                 = sharp, flat
  2017.  */
  2018. xlate(notes)
  2019. char *notes;
  2020. {
  2021.     int time,oct,val;
  2022.     char c;
  2023.     playing = 0;        /*  disable playing */
  2024.     indexp = 0;         /*  reset play index */
  2025.     ticks = 0;          /*  reset clock */
  2026.     while (c = toupper(*notes++))
  2027.     {
  2028.         if(c  > 'G')
  2029.         {   switch(c)
  2030.             {   case 'T':   time = 1;   break;  /*  32nd note */
  2031.                 case 'S':   time = 2;   break;  /*  16th note */
  2032.                 case 'I':   time = 4;   break;  /* Eighth note */
  2033.                 case 'Q':   time = 8;   break;  /* quarter note */
  2034.                 case 'H':   time = 16;  break;  /* half note */
  2035.                 case 'W':   time = 32;  break;  /* whole note */
  2036.             }
  2037.             putp(KEY_ON);               /*  send MIDI note on */
  2038.             putptok();                  /*  send current time */
  2039.             ticks = ticks+time;         /*  add note time/2 */
  2040.             putp(oct+val);              /*  send note value */        
  2041.             putp(gv);                   /*  send global velocity */
  2042.             putp(KEY_ON);               /*  send MIDI note off */
  2043.             putptok();                        
  2044.             ticks = ticks+time;         /*  add note time/2 */
  2045.             putp(oct+val);              /*  send note value */        
  2046.             putp(0);                    /*  send velocity = 0 */
  2047.         }
  2048.         else
  2049.             if(c >= 'A')
  2050.             {   switch(c)
  2051.                 {   case 'C':   val = 0;    break;  /*  key of C */
  2052.                     case 'D':   val = 2;    break;
  2053.                     case 'E':   val = 4;    break;
  2054.                     case 'F':   val = 5;    break;
  2055.                     case 'G':   val = 7;    break;
  2056.                     case 'A':   val = 9;    break;
  2057.                     case 'B':   val = 11;   break;
  2058.                 }
  2059.             }
  2060.             else
  2061.                 if(c >= '0')
  2062.                     oct = 12*(c-'0');
  2063.                 else
  2064.                     switch(c)
  2065.                     {   case '+':   val++;  break;  /*  sharp */
  2066.                         case '-':   val--;  break;  /*  flat */
  2067.                     }
  2068.    }
  2069.     indexp = 0;         /*  reset play index */
  2070.     ticks = 0;          /*  reset clock */
  2071. }
  2072.  
  2073. /*  translate ticks to tocks, then put tocks into the play buffer
  2074.  */
  2075. putptok()
  2076. {
  2077.     tictoc();                   /* ticks --> tocks  */
  2078.     putp(tocks[0]);
  2079.     putp(tocks[1]);
  2080.     putp(tocks[2]);
  2081.     putp(tocks[3]);
  2082. }
  2083.  
  2084. foo()
  2085. {
  2086.     static char *this = 
  2087.     "3CIESGS4CIESGS5CIESGS6CIESGS7CH";
  2088.     xlate(this);
  2089. }
  2090.  
  2091.  
  2092.  
  2093.  
  2094.